#####
# fct_joueur.tcl
#
# Fichier regroupant toutes les fonctions concernant les joueurs
#
#####

#####
# Accesseurs et mutateurs sur les différentes parties de joueur
# Ordre des paramètres : 
# 0. Numéro joueur
# 1. posX
# 2. posY
# 3. angle
# 4. vitesse
# 5. score
# 6. vie
# 7. taux
# 8. pseudo
# 9. date
#####

proc get_joueur_numero {joueur} {
	return [lindex $joueur 0]
}

proc get_joueur_posX {joueur} {
	return [lindex $joueur 1]
}

proc get_joueur_posY {joueur} {
	return [lindex $joueur 2]
}

proc get_joueur_angle {joueur} {
	return [lindex $joueur 3]
}

proc get_joueur_vitesse {joueur} {
	return [lindex $joueur 4]
}

proc get_joueur_score {joueur} {
	return [lindex $joueur 5]
}

proc get_joueur_vie {joueur} {
	return [lindex $joueur 6]
}

proc get_joueur_taux {joueur} {
	return [lindex $joueur 7]
}

proc get_joueur_pseudo {joueur} {
	return [lindex $joueur 8]
}

proc get_joueur_date {joueur} {
	return [lindex $joueur 9]
}

proc set_joueur_posX {joueur value} {
	upvar $joueur x
	set x [lreplace $x 1 1 $value]
}

proc set_joueur_posY {joueur value} {
	upvar $joueur x
	set x [lreplace $x 2 2 $value]
}

proc set_joueur_angle {joueur value} {
	upvar $joueur x
	set x [lreplace $x 3 3 $value]
}

proc set_joueur_vitesse {joueur value} {
	upvar $joueur x
	set x [lreplace $x 4 4 $value]
}

proc set_joueur_score {joueur value} {
	upvar $joueur x
	set x [lreplace $x 5 5 $value]
}

proc set_joueur_vie {joueur value} {
	upvar $joueur x
	set x [lreplace $x 6 6 $value]
}

proc set_joueur_taux {joueur value} {
	upvar $joueur x
	set x [lreplace $x 7 7 $value]
}

proc set_joueur_pseudo {joueur value} {
	upvar $joueur x
	set x [lreplace $x 8 8 $value]
}

proc set_joueur_date {joueur value} {
	upvar $joueur x
	set x [lreplace $x 9 9 $value]
}


#Entrée : numero du joueur
#Sortie : liste contenant le numero du joueur
#
#Comportement : parcourt la table des joueurs jusqu'à trouver le numéro de joueur correspond au paramètre entré
proc recherche_numero_joueur {numero_joueur} {
	global table_joueurs
	global _debug
	
	if {$_debug} {
		puts "Recherche numéro joueur $numero_joueur"
	}
	
	foreach i [lindex $table_joueurs 0] {
		set tmp [lsearch [get_joueur_numero $i] $numero_joueur]
		if {$tmp==0} {
			return $i
		}
	}
}

#Entrée : numéro du joueur
#Sortie : rien
#
#Comportement : Recherche le numéro du joueur dans la table des joueurs et le supprime s'il est présent
proc supprimer_joueur {numero_joueur} {
	global table_joueurs
	global _debug
	
	#calcul du nombre de joueur dans table_joueurs
	set longueur_liste [llength [lindex $table_joueurs 0]]
	
	#si la table_joueurs n'est pas vide on cherche la liste contenant joueur à supprimer
	if {$longueur_liste >= 1} {
		set j 0
		foreach i [lindex $table_joueurs 0] {
			#on cherche joueur dans la liste 
			set tmp [lsearch [get_joueur_numero $i] $numero_joueur]
			incr j
			#si le joueur est trouvé on le supprime de la table_joueurs
			if {$tmp == 0} {	
				set table_joueurs [list [lreplace [lindex $table_joueurs 0] [expr $j - 1] [expr $j- 1]]]
			}			
		}
	}
	
	if {$_debug} {
		puts "Supprime joueur $numero_joueur"
	}
}

#Entrée : un joueur dans la liste des joueurs, deux entiers correspondants à deux coordonnées
#Sorties : un entier, distance entre le joueur et le point en position [posX,posY]
#
#Comportement : calcul de la position selon la formule classique
proc distance {joueur posX posY} {
	global _debug
	
	set joueur_posX [get_joueur_posX $joueur]
	set joueur_posY [get_joueur_posY $joueur]
	set distance_X [expr {pow(($posX - $joueur_posX),2)}]
	set distance_Y [expr {pow(($posY - $joueur_posY),2)}]
	set distance [expr {int(sqrt(($distance_X + $distance_Y)))}]
	
	if {$_debug} {
		puts "Distance calculée"
	}
	
	return $distance
}

#Entrée : liste correspondant à un joueur
#Sortie : rien
#
#Comportement : ajoute un joueur à la table des joueurs
proc ajouter_joueur_joueur {nouveau_joueur} {
	global table_joueurs
	global _debug

	set numero_joueur [get_joueur_numero $nouveau_joueur]
	set trouve_joueur 0

	foreach i [lindex $table_joueurs 0] {
		set tmp [lsearch [get_joueur_numero $i] $numero_joueur]
		if {$tmp > -1} {
			set trouve_ast 1
		}
	}
	
	if {$trouve_joueur == 0} {
		set table_joueurs [list [linsert [lindex $table_joueurs 0] end $nouveau_joueur]]
	}
	
	if {$_debug} {
		puts "Joueur $nouveau_joueur ajouté"
	}
}

#Entrée : joueur sous forme de liste
#Sortie : rien
#
#Comportement : mets à joueur le joueur passé en paramètres
proc maj_joueur {joueur} {
	global table_joueurs
	global _debug
	
	set longueur_liste [llength [lindex $table_joueurs 0]]
	set numero_joueur [get_joueur_numero $joueur]
	
	if {$longueur_liste >= 1} {
		set j 0
		foreach i [lindex $table_joueurs 0] {
			#on cherche joueur dans la liste 
			set tmp [lsearch [get_joueur_numero $i] $numero_joueur]
			#si le joueur est trouvé on le modifie dans la table_joueurs
			if {$tmp == 0} {
				set table_joueurs [list [lreplace [lindex $table_joueurs 0] $j $j $joueur]]
			}
			incr j
		}
	}
	if {$_debug} {
		puts "Joueur $joueur mis à jour"
	}
}

#Entrée : deux listes de joueurs
#Sortie : une seule liste, concaténation des deux
#
#Comportement : dans un premier temps, la procédure vérifie que les joueurs contenus dans chaque liste sont
#existe dans la table des joueurs, et supprimer les intrus. Dans un second temps, les deux listes résultantes
#sont fusionnées, les doublons éliminés et la liste est classée dans l'ordre.
proc fusionner {liste_joueurs1 liste_joueurs2} {
	global table_joueurs
	global _debug
	
	#création d'une liste des numéro de joueurs

	foreach i [lindex $table_joueurs 0] {
		lappend liste_numero_joueur [get_joueur_numero $i]
	}
	
	#Vérification de liste_joueurs1
	set nouvelle_liste_joueurs1 $liste_joueurs1
	set compteur 0
	foreach i $liste_joueurs1 {
		set tmp [lsearch $liste_numero_joueur $i]
		if {$tmp==-1} {
			set nouvelle_liste_joueurs1 [lreplace $nouvelle_liste_joueurs1 $compteur $compteur]
			set compteur [expr $compteur-1]
		}
		incr compteur
	}
	
	set liste_joueurs1 $nouvelle_liste_joueurs1
	
	
	#Vérification de liste_joueurs2
	set nouvelle_liste_joueurs2 $liste_joueurs2
	set compteur 0
	foreach i $liste_joueurs2 {
		set tmp [lsearch $liste_numero_joueur $i]
		if {$tmp==-1} {
			set nouvelle_liste_joueurs2 [lreplace $nouvelle_liste_joueurs2 $compteur $compteur]
			set compteur [expr $compteur-1]
		}
		incr compteur
	}
	
	set liste_joueurs2 $nouvelle_liste_joueurs2
	
	set nouvelle_liste [concat $liste_joueurs1 $liste_joueurs2]
	
	set nouvelle_liste [lrmdups $nouvelle_liste]
	
	if {$_debug} {
		puts "Nouvelle liste formé $nouvelle_liste"
	}
	
	return $nouvelle_liste
}

#Fonction utilitaire pour supprimer les doublons dans une liste
proc lrmdups list {
	array set x {}
	set res {}
	foreach e $list {
		if {[info exists x($e)]} continue
			lappend res $e
			set x($e) {}
		}
	return $res
}
